package com.gxy.learn.sonarqube.runner;

import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.gxy.learn.cu.utils.cmd.CommandClient;
import com.gxy.learn.sonarqube.entity.CodeSonarqube;
import com.gxy.learn.sonarqube.enums.SystemEnum;
import com.gxy.learn.sonarqube.repository.CodeSonarqubeRepository;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.concurrent.*;

/**
 * 根据表配置扫描代码
 *
 * 应用初始化后，去执行一段代码块逻辑，这段初始化代码在整个应用生命周期内只会执行一次。
 */
@Slf4j
@Component
public class SonarqubeApplicationRunner implements CommandLineRunner {


    @Autowired
    private CodeSonarqubeRepository codeSonarqubeRepository;


    ThreadFactory consumptionThreadFactory = new ThreadFactoryBuilder().setNameFormat("sonarqube-scan-%d").build();
    /**
     * maximumPoolSize 不应该超过线程池最小连接数 （spring.datasource.druid.min-idle） 否则会报 get connection timeout retry : 1 异常
     */
    ExecutorService consumptionExecutor = new ThreadPoolExecutor(5, 10,
            0L, TimeUnit.MILLISECONDS,
            new LinkedBlockingQueue<Runnable>(5), consumptionThreadFactory, new RejectedExecutionHandler() {
        @Override
        public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
            if (!executor.isShutdown()) {
                try {
                    executor.getQueue().put(r);
                    log.warn("当前队列阻塞中。。。");
                } catch (InterruptedException e) {
                    // should not be interrupted
                    log.error("阻塞队列出现错误！", e);
                }
            }
        }
    });

    @Override
    public void run(String... args) throws Exception {
        List<CodeSonarqube> list = codeSonarqubeRepository.findAll();
        for (CodeSonarqube codeSonarqube : list) {
            if (SystemEnum.LINUX.getCode().equals(codeSonarqube.getSystem())) {
                consumptionExecutor.submit(() -> {
                    CommandClient client = CommandClient.getInstance(codeSonarqube.getIp(), codeSonarqube.getPort(), codeSonarqube.getName(), codeSonarqube.getPassword());
                    //                mvn clean verify sonar:sonar -D maven.test.skip=true -f /root/yikatongtest/ykt_sass/pom.xml
                    String runLog = client.linuxCmdExec(codeSonarqube.getCommand(), StandardCharsets.UTF_8.displayName());
                    if (StringUtils.isBlank(runLog)) {
                        log.error("执行服务器[{}]的[{}]命令出现错误！", codeSonarqube.getId(), codeSonarqube.getCommand());
                        return;
                    }
                    codeSonarqube.setRunLog(runLog);
                    codeSonarqubeRepository.saveAndFlush(codeSonarqube);
                });
            } else if (SystemEnum.WIN.getCode().equals(codeSonarqube.getSystem())) {
                //win环境目前只测试本地
                consumptionExecutor.submit(() -> {
                    String runLog = CommandClient.winCmdExec(codeSonarqube.getDiskName(), codeSonarqube.getSourcePath(), codeSonarqube.getCommand(), codeSonarqube.getCharsets());
                    if (StringUtils.isBlank(runLog)) {
                        log.error("执行服务器[{}]的[{}]命令出现错误！", codeSonarqube.getId(), codeSonarqube.getCommand());
                        return;
                    }
                    log.info("runLog = {}",runLog);
                    try {
                        codeSonarqube.setRunLog( new String(runLog.getBytes(), "utf-8") );
                        codeSonarqubeRepository.saveAndFlush(codeSonarqube);
                    } catch (UnsupportedEncodingException e) {
                       log.error("err",e);
                    }
                });
            }
        }
    }
}
